﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;


namespace SerializeProject.Formatters
{
    public class JsonFormat:IFormat
    {
        string IFormat.objectTostring(Node obj)
        { 
           StringBuilder builder = new StringBuilder();

           if (obj.IsIEnumerable ==true)
           {
               builder.AppendLine(string.Format("\"{0}\":\n", obj.Name));
               builder.AppendLine("[\n");
               Helper(obj, builder);
               builder.AppendLine("]\n");
           }
           else
           {
               builder.AppendLine("{");
               builder.AppendLine(string.Format("\"{0}\":\n", obj.Name));
               builder.AppendLine("{\n");
               //Helper
               Helper(obj, builder);
               builder.AppendLine("}\n");
               builder.AppendLine("}");
               Trace.WriteLine(builder.ToString()); 
           }
            return builder.ToString();
        }

        Node IFormat.stringToObject(string s)
        {
            var nodesquery = from element in ParseJSONHelper(s)
                             select new
                             {
                                 name = element.Key,
                                 value = element.Value
                             }; 
            
            Node root = new Node
            {
                Name = nodesquery.First().name,
                Value = nodesquery.First().value,
                IsComposedType= true,
                IsRoot = true     
            };
            root.setChildNodes();
            int index;
            for (index = 1; index < nodesquery.Count(); index++)
            {
                Node node = new Node { 
                 Name = nodesquery.ElementAt(index).name,
                 Value = nodesquery.ElementAt(index).value,
                };
                if (String.IsNullOrEmpty(node.Value.ToString()) || node.Value.ToString().Equals(" ") || node.Value.ToString().Equals("\n\r\n"))
                {
                    node.IsComposedType = true;
                }
                root.addChildNode(node);
            }
            return root;
        }

        #region helpers
        private void Helper(Node obj, StringBuilder builder)
        {
            int i;
            if (obj.IsIEnumerable == false)
            {
                i = 0;
                for (i = 0; i < obj.ChildNodes.Count; i++)
                {
                    Node child = obj.ChildNodes[i];
                    if (child.Value.GetType().IsValueType || child.Value.GetType().Equals(typeof(string)))
                    {

                        builder.AppendLine(string.Empty);
                        builder.AppendFormat("\"{0}\":\"{1}\"\n",
                                         obj.ChildNodes[i].Name,
                                         obj.ChildNodes[i].Value);
                        if (i < obj.ChildNodes.Count - 1) builder.Append(",");
                        builder.AppendLine(string.Empty);

                    }
                    else if (child.Value.GetType().IsClass || child.Value.GetType().IsInterface)
                    {
                        builder.AppendLine(string.Format("\"{0}\":\n", child.Name));
                        builder.AppendLine("{\n");
                        Helper(child, builder);
                        builder.AppendLine("}\n");
                    }
                } 
            }
            else 
            {
                i = 0;
                foreach (var item in obj.ChildNodes)
                {
                    builder.AppendLine("{");                   
                    builder.AppendLine(string.Format("\"{0}\"",item.Value));
                    builder.AppendLine("}");
                    if (i++ < obj.ChildNodes.Count - 1) 
                    { 
                        builder.Append(",");
                    }
                }
            }
        }

        private Dictionary<string, string> ParseJSONHelper(string s)
        {
            Dictionary<string, string> jsonDictionary = new Dictionary<string, string>();

                Regex r = new Regex("\"(?<Key>[\\w]*)\":\"?(?<Value>([\\s\\w\\d\\.\\\\\\-/:_\\+]+(,[,\\s\\w\\d\\.\\\\\\-/:_\\+]*)?)*)\"?");
                MatchCollection mc = r.Matches(s);
                if (mc.Count==0)
                {
                    r = new Regex("\"(.+?)\"");
                    mc = r.Matches(s);
                }
                foreach (Match k in mc)
                {
                    jsonDictionary.Add(k.Groups["Key"].Value, k.Groups["Value"].Value);
                } 
            return jsonDictionary;
        }

        #endregion

        
    }
}

